Comparing Stock Market Performance by Presidential Administration
Stock Market Performance By Presidential Administration¶
Introduction¶
Some Americans, including Republican presidential candidates, claim US voters should vote for Republican presidential candidates because the stock market goes up more under Republican presidents.
This isn't a good argument: first, because the president doesn't directly control the values of stocks; second, because, in recent history, the stock market has grown much more under Democratic administrations than republican ones.
Let's take a quick, informal look at the data.
Data Source¶
I'm going to use Yahoo Finance as the data source. It's a free service and it allows you to download stock market quotations by ticker for a specified period of time. I downloaded the data from the Dow Jones Index (^DJI) for the period from 1989-01-20 to 2021-01-15 (the latest date available when I pulled the data) and saved that as the file 'DJIbyPresident.csv'.
I've chosen to use the DJI as a proxy for the stock market as a whole because the 30 companies that are memebers of the Dow represent a huge share of the overall stock market (by market cap). We could have chosen a broader index like the S&P500, or the NASDAQ, but over the 30 year timescale that we've chosen to look at, the differences between the performance of these indices are minor compared to the overall trend over time.
import numpy as np
import pandas as pd
import plotly.express as px
# import data from .csv file
path_to_stock_prices = '../data/DJIbyPresident.csv' # location of the file
stock_prices = pd.read_csv(path_to_stock_prices) # stock_prices is now a dataframe!
# select just the column data we want
filtered_stock_prices = stock_prices[['Date','Adj Close']]
filtered_stock_prices
The adjusted close is the price after adjusting for any divided payouts or stock splits.
Now we can just select the days of presidential inaugurations...
# January 20th isn't always a week day, and the market is closed on weekends, so
# we'll use the last trading day before january 20th as the dates to select
# and for some reason yfinance only gave me dates until jan 15th of 2021...
inauguration_dates = ['1/20/89','1/20/93','1/20/97','1/19/01','1/20/05','1/16/09','1/18/13','1/20/17','1/15/21']
selected_rows = filtered_stock_prices.Date.isin(inauguration_dates)
# generates a series of booleans, True if that row
# is in the list of dates, False otherwise
selected_df = filtered_stock_prices[selected_rows].reset_index(drop=True)
# passing the selected rows to the df lets us
# select only the rows where the series has True
selected_df = selected_df.rename({'Adj Close':'AdjClose'},axis=1)
# rename the ugly field to remove the space
selected_df
Now we will create a second dataframe with the information about the presidential administrations.
# Because there have only been a couple of administrations in the period,
# I did this manually. A smarter way to do it for a large dataset would
# be to scrape the data off of wikipedia.
pres_data = [
['George HW Bush', 'Republican', '1/20/89','1/20/93','first'],
['Bill Clinton I', 'Democrat', '1/20/93','1/20/97','first'],
['Bill Clinton II','Democrat','1/20/97','1/19/01','second'],
['George W Bush I','Republican','1/19/01','1/20/05','first'],
['George W Bush II','Republican','1/20/05','1/16/09','second'],
['Barack Obama I','Democrat','1/16/09','1/18/13','first'],
['Barack Obama II','Democrat','1/18/13','1/20/17','second'],
['Donald Trump','Republican','1/20/17','1/15/21','first']
]
pres_df = pd.DataFrame(pres_data, columns = ['administration','party','start_date','end_date','term'])
pres_df
What we want to do now is calculate the percentage change between the start and ending dates of each administration. Because each administration is the same length of time, four years, we can simply calculate the percentage change as:
$$ change = \frac{(end - start)}{start} \cdot 100 $$If we wanted to bundle administrations together, then we'd have to annualize the return using CAGR, because we'd be comparing administrations that were different lengths of time.
# There's probably an easier way to do this.
start_dates = pres_df['start_date']
end_date = pres_df['end_date']
start_prices = [] # initialize some empty lists for the loops below
end_prices = []
# we're going to loop through each of the start dates and end dates in the
# pres_df dataframe and then get the value of the closing price as of those dates,
# store that value in a list, then add those lists back to the pres_df as new columns
for date in start_dates:
price = selected_df.loc[selected_df['Date'] == date].AdjClose.iloc[0]
# This says 'price equals the value of the
# "close" column in the first row of the dataframe returned
# selecting the row of the selected_df dataframe
# that equals date.'
start_prices.append(price)
for date in end_date:
price = selected_df.loc[selected_df['Date'] == date].AdjClose.iloc[0]
end_prices.append(price)
# and now to add those back to our dataframe
pres_df['start_price'] = start_prices
pres_df['end_price'] = end_prices
# and now we'll calculate a new column with the percentage change
pres_df['percentage_change'] = (pres_df['end_price'] - pres_df['start_price'])/pres_df['start_price'] * 100
pres_df
Let's inspect that visually...
fig = px.bar(
pres_df,
x='administration',
y='percentage_change',
color='party',
color_discrete_map={'Democrat':'blue','Republican':'Red'},
category_orders={'administration':
['George HW Bush',
'Bill Clinton I',
'Bill Clinton II',
'George W Bush I',
'George W Bush II',
'Barack Obama I',
'Barack Obama II',
'Donald Trump']},
title="Percentage Change in DJI by Presidential Administration 1989-2021"
)
fig.show()
Let's summarize further with a simple box plot.
fig = px.box(
pres_df,
x='party',
y='percentage_change',
color='party',
color_discrete_map={'Democrat':'blue','Republican':'Red'},
title="Percentage Change in DJI in R. v D. Administrations 1989-2021"
)
fig.show()
If we wanted to, we could set up a statistical test to evaluate how likely it would be to observe data like these given the hypothesis that the DJI goes up more under Republican presidents than Democratic ones.
However, this is unnecessary. We can already see that the last 30 years offers no support for this hypothesis at all.
Conclusion¶
So, can we conclude from this that Democratic presidents are better than Republican ones for DJI investors?
No.
First, as we said above, the president doesn't directly control stock market prices.
Second, there are a huge number of factors that drive stock prices, and while the president may exert some influence on some of those factors, an analysis in terms of the party of the president is going to be way too simple to explain much of the differences we observe in the stock data.
Third, there have only been eight administrations in the last 32 years, so there isn't a huge amount of data available here. We could try to get more data by extending the time period of the study, but then we run into the problem that parties change their platforms over time. Political party affiliation is a proxy for a set of policy positions, but the further out in time we extend our study, the less similar members of the same party's policy positions will be. Further, the factors that drive the stock market itself changes, and the further back in history we go, the less likely the those factors that explained stock price changes in the past will explain stock prices in the present and near future.
